import React, { memo, useCallback, useEffect, useRef, useState } from 'react';
import { NavLink } from "react-router-dom";

import { 
  getSongDetailAction,
  changeSequenceAction, 
  changeCurrentIndexAndSongAction,
  changeLyricIndexAction
} from "../store/actionCreators";
import { shallowEqual, useDispatch, useSelector } from "react-redux";

import { formatImageSize, formatDate, getPlaySong } from "@/utils/format-utils";

import { PlayerBarWrapper, Control, PlayInfo, Operator } from "./style";
import { Slider, message } from 'antd';
import MyPlayPanel from "../app-player-panel";

const MyPlayerBar = memo(() => {
  const dispatch = useDispatch();
  const audioRef = useRef();
  const [duration, setDuration] = useState(0);
  const [currentPlayTime, setCurrentPlayTime] = useState(0);
  const [sliderValue, setSliderValue] = useState(0);
  const [isSliderChange, setIsSliderChange] = useState(false);
  const [isPlaying, setIsPlaying] = useState(false);
  const [showPanel, setShowPanel] = useState(false);

  /** 2.从redux取出歌曲详情、歌曲播放顺序、歌词数据、歌词索引*/
  const { 
          currentSong, 
          sequence, 
          lyricList,
          lyricIndex,
          playList
        } = useSelector(state => ({
    currentSong: state.getIn(["player", "currentSong"]),
    sequence: state.getIn(["player", "sequence"]),
    lyricList: state.getIn(["player", "lyricList"]),
    lyricIndex: state.getIn(["player", "lyricIndex"]),
    playList: state.getIn(["player", "playList"])
  }), shallowEqual);

  useEffect(() => {
    /** 1.获取歌曲详情保存redux中  写死参数(ids)：29567191*/
    dispatch(getSongDetailAction(1968791360));
  }, [dispatch]);

  /** 7.在模拟生命周期里给audio的src赋值播放地址 */
  useEffect(() => {
    audioRef.current.src = getPlaySong(currentSong.id);
    
    /**9.1改变当前歌曲时，生命周期会执行 play()返回一个promise，如果能播放成功播放状态设为true，反之false*/
    audioRef.current.play().then(res => {
      setIsPlaying(true);
    }).catch(err => {
      setIsPlaying(false);
    });
    setDuration(currentSong.dt);
  }, [currentSong]);

  /** 3.异步数据没回来的处理 */
  const picUrl = (currentSong.al && currentSong.al.picUrl) || "";
  const authorName = (currentSong.ar && currentSong.ar[0].name) || "歌手名";
  // const duration =  currentSong.dt || 0;                     //总时长
  const showDuration = formatDate(duration, "mm:ss");        //展示总时长
  const cTime = formatDate(currentPlayTime, "mm:ss");        //展示当前播放时长 

  /** 4.拿到播放地址url 播放音乐*/
  const playAudio = useCallback(() => {
    // audioRef.current.src = getPlaySong(currentSong.id);
    isPlaying ? audioRef.current.pause() : audioRef.current.play().catch(err => {
      setIsPlaying(false);
    });
    setIsPlaying(!isPlaying);
  }, [isPlaying]);

  /** 5.监听当前的播放时间回调函数  转为毫秒*/
  const timeUpdate = (e) => {
    const currentTime = e.target.currentTime  * 1000;

    /** 6.1手指滑动进度条(sliderChange)播放进度时 这里就不能设置播放时长了, 停止时滑动时(sliderAfterChange)再设置 */
    if (!isSliderChange) {
      setCurrentPlayTime(currentTime);
      /** 随着播放改变当前时间进度条  value是整数值 一定要是最初的播放时间currentTime*/
      setSliderValue(currentTime / duration * 100)
    }

    /** 11.根据当前播放时间去歌词列表查，找到小于歌词时间的这一项停止循环此时i===这一项，然后lyricList[i(这一项索引) - 1]就是最接近当前播放时间的那一项*/
    let i = 0;
    for (; i < lyricList.length; i++) {
      if (currentTime < lyricList[i].time) {
        // console.log(lyricList[i - 1]);
        break;
      }
    }

    //11.1 当前播放的歌词索引记录到redux中，与当前播放歌词索引不相等时才改变，优化for循环。
    if (lyricIndex !== i - 1) {
      dispatch(changeLyricIndexAction(i - 1));
      const content = lyricList[i - 1] && lyricList[i - 1].content;
      content && message.open({
                  key: "lyrics",
                  content,
                  duration: 0,
                  className: "lyric-class"
                });
    }
  };

  /** 6.手指滑动播放进度*/
  const sliderChange = useCallback((value) => {
    setSliderValue(value);

    //移动时改变时间&进度条；
    const currentTime = value / 100 * duration;
    setCurrentPlayTime(currentTime);
    // 6.2开始滑动进度条；
    setIsSliderChange(true);
  }, [duration]);
  const sliderAfterChange = useCallback((value) => {
    //松开前 确定播放时间给audio，因为audio的currentTime属性单位是秒所以 /1000；
    const currentTime = value / 100 * duration / 1000;
    audioRef.current.currentTime = currentTime;
    setCurrentPlayTime(currentTime * 1000);

    // 6.3结束/松开滑动进度条；
    setIsSliderChange(false);

    //7.1 进度条松开时如果是暂停状态，就播放；
    if (!isPlaying) {
      playAudio();
    }
  }, [duration, isPlaying, playAudio]);
  
  /** 8.改变播放顺序 0/顺序 1/随机 2/单曲*/
  const changeSequence = () => {
    let newSequence = sequence + 1;
    if (newSequence > 2) {
      newSequence = 0
    };
    dispatch(changeSequenceAction(newSequence))
  };

  /** 9.下一首/上一首 */
  const changeMusic = (tag) => {
    dispatch(changeCurrentIndexAndSongAction(tag))
  };

  /**10.音乐播放结束 */
  const musicEnded = () => {
    if (sequence === 2) {  //单曲循环 
      audioRef.current.currentTime = 0;
      audioRef.current.play();
    } else {  //顺序/随机 按下一曲播放
      dispatch(changeCurrentIndexAndSongAction(1))
    }
  };

  /** 12. 关闭panel */
  const handlerIsShowPanel = () => {
    setShowPanel(!showPanel)
  };

  return (
    <PlayerBarWrapper className="sprite_player">
      <div className="content wrap-v2">
        <Control isPlaying={isPlaying}>
          <button className="sprite_player prev" onClick={e => changeMusic(-1)}></button>
          <button className="sprite_player play" onClick={e => playAudio()}></button>
          <button className="sprite_player next" onClick={e => changeMusic(1)}></button>
        </Control>

        <PlayInfo>
          <div className="image">
            <NavLink to="/discover/player">
              <img src={formatImageSize(picUrl, 34)}alt="" />
            </NavLink>
          </div>

          <div className="info">
            <div className="song">
              <span className="song-name">{currentSong.name}</span>
              <a href="#/" className="singer-name">{authorName}</a>
            </div>

            <div className="progress">
              <Slider
                value={sliderValue} 
                onChange={sliderChange}
                onAfterChange={sliderAfterChange}
              />
              <div className="time">
                <span className="now-time">{cTime}</span>
                <span className="divider">/</span>
                <span className="duration">{showDuration}</span>
              </div>
            </div>
          </div>
        </PlayInfo>

        <Operator sequence={sequence}>
          <div className="left">
            <button className="sprite_player btn favor"></button>
            <button className="sprite_player btn share"></button>
          </div>

          <div className="right sprite_player">
            <button className="sprite_player btn volume"></button>
            <button className="sprite_player btn loop" onClick={e => changeSequence()}></button>
            <button 
              className="sprite_player btn playlist"
              onClick={e => handlerIsShowPanel()}
            >
              <span>{playList.length}</span>
            </button>
          </div>
        </Operator>
      </div>

      {/* 播放音频 */}
      <audio 
        ref={audioRef} 
        onTimeUpdate={timeUpdate}
        onEnded={musicEnded} 
      />

      {/* 面板组件 */}
      { showPanel && <MyPlayPanel handlerIsShowPanel={handlerIsShowPanel} />}
    </PlayerBarWrapper>
  )
})

export default MyPlayerBar